home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / edit / jed207.lha / src / jed.lha / keys.c < prev    next >
C/C++ Source or Header  |  1993-01-05  |  10KB  |  438 lines

  1.  
  2. /*
  3.  * KEYS.C
  4.  * (c) 1992-3 J.Harper
  5.  */
  6.  
  7. #include "jed.h"
  8. #include "jed_protos.h"
  9.  
  10. Prototype   VALUE * cmd_bind        (LONG, VALUE *);
  11. Prototype   VALUE * cmd_unbind        (LONG, VALUE *);
  12. Prototype   VOID    killbindings    (VOID);
  13. Local        STRPTR  evalbinding        (UBYTE, UWORD);
  14. Prototype   VOID    usekey        (struct IntuiMessage *);
  15. Local        ULONG   descrtoraw        (STRPTR);
  16. Local        BOOL    cmpquals        (UWORD, UWORD);
  17.  
  18. #define HARDCODE_CURSOR
  19.  
  20. #define UNPAIREDQUALS (IEQUALIFIER_CONTROL | IEQUALIFIER_NUMERICPAD | \
  21.     IEQUALIFIER_MIDBUTTON | IEQUALIFIER_RBUTTON | IEQUALIFIER_LEFTBUTTON)
  22. #define SHIFTQUALS (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  23. #define ALTQUALS   (IEQUALIFIER_LALT | IEQUALIFIER_RALT)
  24. #define CMDQUALS   (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND)
  25.  
  26. typedef struct KEY
  27. {
  28.     struct KEY     *ky_Next;
  29.     UWORD      ky_Qual;
  30.     STRPTR      ky_Cmd;
  31. } KEY;
  32.  
  33. Local KEY *KeyHash[128];
  34.  
  35. typedef struct KEYDESC
  36. {
  37.     STRPTR      kd_Name;
  38.     BOOL      kd_IsCode;
  39.     UWORD      kd_Value;
  40. } KEYDESC;
  41.  
  42. Local const KEYDESC KeyDescr[] =
  43. {
  44.     "SHIFT",      FALSE, SHIFTQUALS,
  45.     "ALT",        FALSE, ALTQUALS,
  46.     "COMMAND",    FALSE, CMDQUALS,
  47.     "AMIGA",      FALSE, CMDQUALS,
  48.     "CONTROL",    FALSE, IEQUALIFIER_CONTROL,
  49.     "CTRL",       FALSE, IEQUALIFIER_CONTROL,
  50.     "NUMERICPAD", FALSE, IEQUALIFIER_NUMERICPAD,
  51.     "LMB",        FALSE, IEQUALIFIER_LEFTBUTTON,
  52.     "MMB",        FALSE, IEQUALIFIER_MIDBUTTON,
  53.     "RMB",        FALSE, IEQUALIFIER_RBUTTON,
  54.  
  55.     "SPACE",      TRUE,  0x40,
  56.     "BACKSPACE",  TRUE,  0x41,
  57.     "TAB",        TRUE,  0x42,
  58.     "ENTER",      TRUE,  0x43,
  59.     "RETURN",     TRUE,  0x44,
  60.     "ESC",        TRUE,  0x45,
  61.     "ESCAPE",     TRUE,  0x45,
  62.     "DEL",        TRUE,  0x46,
  63.     "DELETE",     TRUE,  0x46,
  64.     "HELP",       TRUE,  0x5f,
  65.     "UP",         TRUE,  0x4c,
  66.     "DOWN",       TRUE,  0x4d,
  67.     "RIGHT",      TRUE,  0x4e,
  68.     "LEFT",       TRUE,  0x4f,
  69.     "F1",         TRUE,  0x50,
  70.     "F2",         TRUE,  0x51,
  71.     "F3",         TRUE,  0x52,
  72.     "F4",         TRUE,  0x53,
  73.     "F5",         TRUE,  0x54,
  74.     "F6",         TRUE,  0x55,
  75.     "F7",         TRUE,  0x56,
  76.     "F8",         TRUE,  0x57,
  77.     "F9",         TRUE,  0x58,
  78.     "F10",        TRUE,  0x59,
  79.     NULL, 0, 0
  80. };
  81.  
  82. /*
  83.  * Structure to fix problems with binding to numeric pad keys.
  84.  * actually this may not work properly on some weird keymaps.
  85.  */
  86. typedef struct NUMDESC
  87. {
  88.     STRPTR      nd_Name;        /* char to map */
  89.     UBYTE      nd_TypewriterKey; /* rawkey for typewriter */
  90.     UBYTE      nd_TypewriterQual;
  91.     UBYTE      nd_NumericKey;    /* rawkey for numeric */
  92. } NUMDESC;
  93.  
  94. Local const NUMDESC NumDescr[] =
  95. {
  96.     "(", 0x09, SHIFTQUALS, 0x5c,
  97.     ")", 0x0a, SHIFTQUALS, 0x5b,
  98.     "/", 0x3a, 0,          0x5c,
  99.     "*", 0x08, SHIFTQUALS, 0x5d,
  100.     "7", 0x07, 0,          0x3d,
  101.     "8", 0x08, 0,          0x3e,
  102.     "9", 0x09, 0,          0x3f,
  103.     "-", 0x0b, 0,          0x4a,
  104.     "4", 0x04, 0,          0x2d,
  105.     "5", 0x05, 0,          0x2e,
  106.     "6", 0x06, 0,          0x2f,
  107.     "+", 0x0c, SHIFTQUALS, 0x5e,
  108.     "1", 0x01, 0,          0x1d,
  109.     "2", 0x02, 0,          0x1e,
  110.     "3", 0x03, 0,          0x1f,
  111.     "0", 0x0a, 0,          0x0f,
  112.     ".", 0x39, 0,          0x3c,
  113.     0, 0, 0, 0
  114. };
  115.  
  116. /*
  117.  * (bind {`keyDescr' `command'})
  118.  */
  119. VALUE *
  120. cmd_bind(LONG argc, VALUE *argv)
  121. {
  122.     VALUE *res = &RES;
  123.     BOOL rc = TRUE;
  124.     while(rc && (argc >= 2))
  125.     {
  126.     if(TPLATE2(VTF_STRING, VTF_STRING))
  127.     {
  128.         KEY *newkey;
  129.         LONG keyqual;
  130.         if(newkey = AllocVec(sizeof(KEY), MEMF_CLEAR))
  131.         {
  132.         if(((keyqual = descrtoraw(ARG1.val_Value.String)) != -1) && ((UBYTE)keyqual < IECODE_UP_PREFIX))
  133.         {
  134.             newkey->ky_Qual = (WORD)(keyqual >> 16);
  135.             if(newkey->ky_Cmd = savestring(ARG2.val_Value.String))
  136.             {
  137.             newkey->ky_Next = KeyHash[(UBYTE)keyqual];
  138.             KeyHash[(UBYTE)keyqual] = newkey;
  139.             }
  140.             else
  141.             {
  142.             settitle(NoMemMsg);
  143.             FreeVec(newkey);
  144.             rc = FALSE;
  145.             }
  146.         }
  147.         else
  148.         {
  149.             FreeVec(newkey);
  150.             rc = FALSE;
  151.         }
  152.         }
  153.         else
  154.         {
  155.         settitle(NoMemMsg);
  156.         rc = FALSE;
  157.         }
  158.     }
  159.     else
  160.         goto abort;
  161.     argc -= 2;
  162.     argv += 2;
  163.     }
  164.     res->val_Type = VTF_NUMBER;
  165.     res->val_Value.Number = rc;
  166. abort:
  167.     return(res);
  168. }
  169.  
  170. /*
  171.  * (unbind {`keyDescr'})
  172.  */
  173. VALUE *
  174. cmd_unbind(LONG argc, VALUE *argv)
  175. {
  176.     VALUE *res = &RES;
  177.     BOOL rc = TRUE;
  178.     while(rc && (argc >= 1))
  179.     {
  180.     if(TPLATE1(VTF_STRING))
  181.     {
  182.         LONG keyqual;
  183.         if(keyqual = descrtoraw(ARG1.val_Value.String))
  184.         {
  185.         KEY *thiskey, *prevkey = NULL;
  186.         UBYTE index = (UBYTE)keyqual;
  187.         if(thiskey = KeyHash[index])
  188.         {
  189.             while(thiskey)
  190.             {
  191.             if(thiskey->ky_Qual == (WORD)(keyqual >> 16))
  192.                 break;
  193.             prevkey = thiskey;
  194.             thiskey = thiskey->ky_Next;
  195.             }
  196.             if(thiskey)
  197.             {
  198.             if(prevkey)
  199.                 prevkey->ky_Next = thiskey->ky_Next;
  200.             else
  201.                 KeyHash[index] = thiskey->ky_Next;
  202.             freestring(thiskey->ky_Cmd);
  203.             FreeVec(thiskey);
  204.             }
  205.         }
  206.         else
  207.         {
  208.             settitle("error: key not bound to anything");
  209.             rc = FALSE;
  210.         }
  211.         }
  212.     }
  213.     else
  214.         goto abort;
  215.     argc--;
  216.     argv++;
  217.     }
  218.     res->val_Type = VTF_NUMBER;
  219.     res->val_Value.Number = rc;
  220. abort:
  221.     return(res);
  222. }
  223.  
  224. VOID
  225. killbindings(VOID)
  226. {
  227.     LONG i;
  228.     for(i = 0; i < 128; i++)
  229.     {
  230.     KEY *thiskey;
  231.     thiskey = KeyHash[i];
  232.     while(thiskey)
  233.     {
  234.         KEY *nextkey = thiskey->ky_Next;
  235.         freestring(thiskey->ky_Cmd);
  236.         FreeVec(thiskey);
  237.         thiskey = nextkey;
  238.     }
  239.     KeyHash[i] = NULL;
  240.     }
  241. }
  242.  
  243. Local STRPTR
  244. evalbinding(UBYTE key, UWORD qual)
  245. {
  246.     if(key < IECODE_UP_PREFIX)
  247.     {
  248.     KEY *thiskey;
  249.     if(thiskey = KeyHash[key])
  250.     {
  251.         while(thiskey)
  252.         {
  253.         if(cmpquals(thiskey->ky_Qual, qual))
  254.             break;
  255.         thiskey = thiskey->ky_Next;
  256.         }
  257.         if(thiskey)
  258.         return(thiskey->ky_Cmd);
  259.     }
  260.     }
  261.     return(FALSE);
  262. }
  263.  
  264. VOID
  265. usekey(struct IntuiMessage *im)
  266. {
  267.     UWORD key = im->Code;
  268.     UWORD qual = im->Qualifier;
  269.     STRPTR cmd;
  270.  
  271.     qual &= ~(IEQUALIFIER_REPEAT | IEQUALIFIER_INTERRUPT | IEQUALIFIER_MULTIBROADCAST | IEQUALIFIER_RELATIVEMOUSE);
  272.     resettitle();
  273.     cursor(OFF);
  274.     if(cmd = evalbinding(key, qual))
  275.     {
  276.     VALUE result;
  277.     execstr(cmd, &result, FALSE, 0, NULL);
  278.     releasevalue(&result);
  279.     }
  280.     else
  281.     {
  282. #ifdef HARDCODE_CURSOR
  283.     switch(key)
  284.     {
  285.         case 0x4c:
  286.         if(!(qual & ~IEQUALIFIER_CAPSLOCK))
  287.             moveuplines(1);
  288.         else if(qual & SHIFTQUALS)
  289.             moveuppages(1);
  290.         else if(qual & IEQUALIFIER_CONTROL)
  291.             movesof();
  292.         break;
  293.         case 0x4d:
  294.         if(!(qual & ~IEQUALIFIER_CAPSLOCK))
  295.             movedownlines(1);
  296.         else if(qual & SHIFTQUALS)
  297.             movedownpages(1);
  298.         else if(qual & IEQUALIFIER_CONTROL)
  299.             moveeof();
  300.         break;
  301.         case 0x4e:
  302.         if(!(qual & ~IEQUALIFIER_CAPSLOCK))
  303.             moveright(1);
  304.         else if(qual & SHIFTQUALS)
  305.             moveeol();
  306.         else if(qual & IEQUALIFIER_CONTROL)
  307.             movenextword(1);
  308.         break;
  309.         case 0x4f:
  310.         if(!(qual & ~IEQUALIFIER_CAPSLOCK))
  311.             moveleft(1);
  312.         else if(qual & SHIFTQUALS)
  313.             movesol();
  314.         else if(qual & IEQUALIFIER_CONTROL)
  315.             moveprevword(1);
  316.         break;
  317.         default:
  318. #endif
  319.         UBYTE buff[256];
  320.         LONG len;
  321.         struct InputEvent ie;
  322.  
  323.         ie.ie_Class = IECLASS_RAWKEY;
  324.         ie.ie_SubClass = 0;
  325.         ie.ie_Code = key;
  326.         ie.ie_Qualifier = qual;
  327.         ie.ie_EventAddress = *((APTR *)im->IAddress);
  328.         if((len = MapRawKey(&ie, buff, 255, NULL)) > 0)
  329.         {
  330.             VW *vw = CurrVW;
  331.             setrefresh(RFF_LINEFROM, vw->vw_CursorPos.pos_Col, vw->vw_CursorPos.pos_Line);
  332.             buff[len] = 0;
  333.             padcursor();
  334.             if((vw->vw_Prefs.prf_WordWrap) && ((vw->vw_CursorPos.pos_Col + len) > vw->vw_Prefs.prf_RightMargin))
  335.             wrapline();
  336.             insertstrn(buff, len);
  337.             resyncxy();
  338.             vw->vw_Tx->tx_Changes++;
  339.         }
  340.         else if(len < 0)
  341.             settitle("error: key buffer screwup");
  342. #ifdef HARDCODE_CURSOR
  343.         break;
  344.     }
  345. #endif
  346.     refresh();
  347.     }
  348.     cursor(ON);
  349. }
  350.  
  351. /*
  352.  * Gets a packed set of rawkey and qualifier from an input description.
  353.  * Qualifier is high 16 bits, rawkey is low 16. Returns -1 if an error.
  354.  */
  355. Local ULONG
  356. descrtoraw(STRPTR desc)
  357. {
  358.     STRPTR str = desc;
  359.     UWORD qual = 0;
  360.  
  361.     for(;;)
  362.     {
  363.     UBYTE buff[100];
  364.     KEYDESC *kd = KeyDescr;
  365.  
  366.     str = stpblk(cpynotspc(buff, str));
  367.     while(kd->kd_Name)
  368.     {
  369.         if(!stricmp(kd->kd_Name, buff))
  370.         {
  371.         if(!kd->kd_IsCode)
  372.         {
  373.             qual |= kd->kd_Value;
  374.             break;
  375.         }
  376.         else
  377.             return(((ULONG)qual << 16) | ((ULONG)kd->kd_Value));
  378.         }
  379.         kd++;
  380.     }
  381.     if(!kd->kd_Name)
  382.     {
  383.         NUMDESC *nd = NumDescr;
  384.         UBYTE coded[2];
  385.         while(nd->nd_Name)
  386.         {
  387.         if(!strcmp(nd->nd_Name, buff))
  388.         {
  389.             if(qual & IEQUALIFIER_NUMERICPAD)
  390.             return(((ULONG)qual << 16) | ((ULONG)nd->nd_NumericKey));
  391.             else
  392.             {
  393.             qual |= nd->nd_TypewriterQual;
  394.             return(((ULONG)qual << 16) | ((ULONG)nd->nd_TypewriterKey));
  395.             }
  396.         }
  397.         nd++;
  398.         }
  399.         if(MapANSI(buff, strlen(buff), coded, 1, NULL) == 1)
  400.         {
  401.         qual |= (UWORD)coded[1];
  402.         return(((ULONG)qual << 16) | ((ULONG)coded[0]));
  403.         }
  404.         settitlefmt("error: invalid key description %s", (LONG)desc);
  405.         return(-1);
  406.     }
  407.     }
  408. }
  409.  
  410. /*
  411.  * I'm sure there's an easier way to compare qualifiers (treating the paired
  412.  * keys (eg lshift and rshift) as equivalent), however, I can't think of it.
  413.  */
  414. Local BOOL
  415. cmpquals(UWORD qual1, UWORD qual2)
  416. {
  417.     if((qual1 & UNPAIREDQUALS) == (qual2 & UNPAIREDQUALS))
  418.     {
  419.     UWORD res1, res2;
  420.     res1 = qual1 & SHIFTQUALS;
  421.     res2 = qual2 & SHIFTQUALS;
  422.     if((!res1 && !res2) || (res1 && res2))
  423.     {
  424.         res1 = qual1 & ALTQUALS;
  425.         res2 = qual2 & ALTQUALS;
  426.         if((!res1 && !res2) || (res1 && res2))
  427.         {
  428.         res1 = qual1 & CMDQUALS;
  429.         res2 = qual2 & CMDQUALS;
  430.         if((!res1 && !res2) || (res1 && res2))
  431.             return(TRUE);
  432.         }
  433.     }
  434.     }
  435.     return(FALSE);
  436. }
  437.  
  438.